import xml.dom.minidom as Dom
import os
import sys

suffix = '.xml'

# TODO:hive spark路径完善
HADOOP_CONFS = ['core-site', 'hdfs-site', 'yarn-site', 'mapred-site']
HIVE_CONFS = ['hive-site']
HBASE_CONFS = ['hbase-site']

hadoop = {(i, os.environ.get('HADOOP_CONF_DIR')) for i in HADOOP_CONFS}
hive = {(i, os.environ.get('HIVE_CONF_DIR')) for i in HIVE_CONFS}
hbase = {(i, os.environ.get('HBASE_CONF_DIR')) for i in HBASE_CONFS}
conf_dirs = dict(hadoop.union(hive, hbase))

properties_path = os.path.join(os.path.dirname(__file__), 'conf.properties')


def print_usage():
    print("""
  Usage: python setConf.py conf_name

  eg: core-site hadoop-env hdfs-site mapred-site oozie-site spark-defaults yarn-site
  """)
    exit(1)


def add_property(string: str, doc: Dom.Document):
    """
    将读取到的配置写入xml
    """
    kv = string.split('=')
    root: dom.Node = doc.lastChild
    prop = doc.createElement('property')
    name = doc.createElement('name')
    value = doc.createElement('value')
    root.appendChild(prop)
    name.appendChild(doc.createTextNode(kv[0]))
    value.appendChild(doc.createTextNode(kv[1]))
    prop.appendChild(name)
    prop.appendChild(value)


def save_xml(conf_path: str, doc: Dom.Document):
    """
    将xml落地到磁盘conf_path路径下
    """
    # 检查配置文件是否已存在，存在则删除已有文件
    check_exists(conf_path)

    with open(conf_path, 'w', encoding='utf-8') as f:
        doc.writexml(f, addindent='  ', newl='\n', encoding='utf-8')
    print(str.format("文件写入 {} 成功。", conf_path))


def check_os():
    """
    1:windows 2:linux 3:macos
    """
    os_type = os.environ.get('OS')
    if os_type and 'Windows' in os_type:
        return 1
    elif os_type and 'Linux' in os_type:
        return 2
    elif os_type and 'Mac' in os_type:
        return 3
    else:
        return 2


def check_exists(file_name):
    if os.path.exists(file_name):
        os.remove(file_name)


def read_conf(path: str, prefix: str) -> list:
    """
    读取路径下以prefix开头的配置项，并放入list
    """
    with open(str.format(path), 'r', encoding='utf-8') as f:
        lines = [l.replace(prefix+'_', '').replace('\n', '')
                 for l in f.readlines() if l.startswith(prefix)]
        print('find ', lines)
        return lines


def init_doc(filepath: str):
    """
    用来检测配置文件是否存在。
    如果配置文件存在，
    则根据现有配置文件来生成新的文件，
    否则根据预定义的格式重新创建配置文件
    """
    if os.path.exists(filepath):
        doc = Dom.parse(filepath)
        root: Dom.Node = doc.lastChild
        for i in root.childNodes:
            root.removeChild(i)
    else:
        doc = Dom.Document()
        xlstNode = doc.createProcessingInstruction(
            'xml-stylesheet', 'type=\"text/xsl\" href=\"configuration.xsl\"')
        root = doc.createElement('configuration')
        doc.appendChild(xlstNode)
        doc.appendChild(root)
    return doc


def get_conf_dir(prefix: str) -> str:
    """
    获取配置文件目录
    """
    if check_os() == 1:
        return None
    else:
        return conf_dirs.get(prefix)


def gen_xml(conf_dir: str, prefix: str):
    """
    根据提供的prefix生成配置文件内容，存储在conf_dir下
    """
    conf_path = os.path.join(conf_dir, prefix+suffix)
    doc = init_doc(conf_path)
    lines = read_conf(properties_path, prefix)
    for line in lines:
        add_property(line, doc)
    save_xml(conf_path, doc)


if __name__ == "__main__":
    if len(sys.argv) > 1 and sys.argv[1] in conf_dirs:
        for prefix in sys.argv[1:]:
            conf_dir = get_conf_dir(prefix)
            gen_xml(conf_dir, prefix)
            print(str.format("生成配置文件:{}.xml", prefix))
            if prefix in HIVE_CONFS:
                for name in HADOOP_CONFS:
                    gen_xml(conf_dir, name)
    else:
        print_usage()
